package com.zenithmind.gateway.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 网关全局异常处理
 */
@Order(-1)
@Configuration
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 处理服务器网页交换中的异常
     *
     * 此方法用于处理在执行ServerWebExchange过程中发生的异常它负责向客户端发送适当的错误响应
     * 包含异常信息和状态码通过此方法，可以统一处理异常，提高代码的可维护性和可读性
     *
     * @param exchange 服务器网页交换对象，包含请求和响应等信息
     * @param ex 抛出的异常对象，用于获取异常信息
     * @return 返回一个Mono<Void>，表示异步处理完成
     */
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        // 获取响应对象，用于设置响应状态码和内容
        ServerHttpResponse response = exchange.getResponse();

        // 设置响应的状态码
        if (ex instanceof ResponseStatusException) {
            // 如果异常是ResponseStatusException类型，则使用其状态码
            response.setStatusCode(((ResponseStatusException) ex).getStatusCode());
        } else {
            // 否则，默认使用INTERNAL_SERVER_ERROR状态码
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        // 设置响应类型为JSON
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        // 构建响应内容
        String errorMessage = "{\"code\":" + response.getStatusCode().value() + ", \"message\":\"" + ex.getMessage() + "\"}";
        DataBuffer buffer = response.bufferFactory().wrap(errorMessage.getBytes(StandardCharsets.UTF_8));

        // 记录错误日志，包含异常信息和堆栈跟踪
        logger.error("网关异常: {}", ex.getMessage(), ex);

        // 使用Mono.just(buffer)异步写入响应
        return response.writeWith(Mono.just(buffer));
    }
} 